//
//  TestParticleSystem.cpp
//  NanoOSX
//
//  Created by Jeppe Nielsen on 9/9/13.
//  Copyright (c) 2013 Jeppe Nielsen. All rights reserved.
//

#include "Engine.hpp"
#include "GameState.hpp"
#include "GameWorld.hpp"
#include "RenderSystem.hpp"
#include "Touchable.hpp"
#include "Material.hpp"
#include "TextureComponent.hpp"
#include "FirstPersonMoverSystem.hpp"
#include "TouchSystem.hpp"
#include "Light.hpp"
#include "SpriteMeshSystem.hpp"
#include "LabelMeshSystem.hpp"
#include "TransformHierarchy.hpp"
#include "SpriteTextureSystem.hpp"
#include "Plane.hpp"
#include "Timer.hpp"
#include "ParticleUpdaterSystem.hpp"
#include "ParticleMeshUpdater.hpp"

using namespace Nano;
using namespace std;

class TestParticleSystem : public GameState<TestParticleSystem> {
    void Initialize() {
    /*
        GameObject* go1 = world.CreateObject();
        go1->AddComponent<Transform>()->Position = {1,2,3};
        
        GameObject* go2 = go1->Clone();
        Transform* trans1 = go1->GetComponent<Transform>();
        Transform* trans2 = go2->GetComponent<Transform>();
        
        Transform* owner1 = trans1->World.GetOwner();
        Transform* owner2 = trans2->World.GetOwner();
        
        Matrix4x4* world1 = trans1->World.GetValue();
        Matrix4x4* world2 = trans2->World.GetValue();
      */
        renderTime = 0;
        renderCounter = 0;
        
        renderer = world.CreateSystem<RenderSystem>();
        world.CreateSystem<FirstPersonMoverSystem>()->Input = &Input;
        world.CreateSystem<ParticleUpdaterSystem>();
        world.CreateSystem<ParticleMeshUpdater>();
        
       // atlas = world.CreateObject();
       // atlas->AddComponent<Atlas>()->Load("images.xml", 1024);
       // atlas->AddComponent<TextureComponent>()->Texture().LoadFromPng("images.png");
        
        
        GameObject* camera = world.CreateObject();
        camera->AddComponent<Camera>()->Viewport = Manager().Viewport();
        camera->AddComponent<Transform>()->Position = Vector3(0,0,4);
        camera->AddComponent<FirstPersonMover>();
        
        effect = world.CreateObject();
        ParticleEffect* e = effect->AddComponent<ParticleEffect>();
        e->Duration = 1000;
        e->EmissionFrequency = 0.01f;
        e->EmissionAmount = 2;
        e->Lifetime = { 1.5f, 2.5f };
        
        e->Color.Add(Colour::White(), 0);
        e->Color.Add({ Colour::Red(), Colour::Blue() }, 0.3f);
        e->Color.Add(Colour(1.0f,1.0f,1.0f,0.0f), 1);
        
        e->Velocity.Add({ Vector3(-4,20,-4), Vector3(4,20,4) }, 0.0f);
        
        e->Acceleration.Add(Vector3(0,-30,0), 0.0f);
        
        
        GameObject* texture = world.CreateObject();
        texture->AddComponent<TextureComponent>()->Texture().LoadFromPng("particle.png");
        
        GameObject* cube = world.CreateObject();
        cube->AddComponent<Transform>();
        cube->AddComponent<Mesh>()->AddCube(0, 1);
        //cube->AddComponent<Material>();
        //cube->AddComponent<TextureComponent>(texture);
        
        
        
        emitter = world.CreateObject();
        emitter->AddComponent<ParticleEffect>(effect);
        emitter->AddComponent<ParticleEmitter>()->Playing = true;
        emitter->AddComponent<Material>()->BlendMode = BlendMode::Add;
        emitter->AddComponent<Mesh>();
        emitter->AddComponent<TextureComponent>(texture);
        
        
        GameObject* emitterInstance = world.CreateObject();
        emitterInstance->AddComponent<Transform>()->Position = 0;
        emitterInstance->AddComponent<Mesh>(emitter);
        emitterInstance->AddComponent<Material>(emitter);
        emitterInstance->AddComponent<TextureComponent>(emitter);
        emitterInstance->AddComponent<ParticleEmitter>(emitter);
       
        
        for (int z=0; z<20; z++) {
            for (int x=0; x<20; x++) {
                GameObject* clone = emitterInstance->Clone();
                clone->GetComponent<Transform>()->Position = Vector3(x*10,0,z*10);
                //clone->GetComponent<Transform>()->Scale = 1.0f - x*0.15f;
                //CreateEmitter(emitter, Vector3(x*10,0,z*10));
            }
        }
    }
    
    void CreateEmitter(GameObject* emitter, Vector3 position) {
        GameObject* emitterInstance = world.CreateObject();
        emitterInstance->AddComponent<Transform>()->Position = position;
        emitterInstance->AddComponent<Mesh>(emitter);
        emitterInstance->AddComponent<Material>(emitter);
        emitterInstance->AddComponent<TextureComponent>(emitter);
        emitterInstance->AddComponent<ParticleEmitter>(emitter);
    
    }
        
    void Update(float dt) {
        world.Update(dt);
    }
    
    void Render() {
        glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_CULL_FACE);
        renderTimer.Begin();
        renderer->Render();
        renderTime += renderTimer.End();
        renderCounter++;
        if (renderCounter>20) {
            renderTime /= renderCounter;
            cout<<"Render() time = " << (1.0 / renderTime) << endl;
            renderCounter=0;
        }
    }
    
    GameWorld world;
    RenderSystem* renderer;
    GameObject* effect;
    GameObject* emitter;
    GameObject* atlas;
    Camera* cam;
    Timer renderTimer;
    double renderTime;
    int renderCounter;
};

/*
int main() {
    Engine e;
    e.Start<TestParticleSystem>();
}
*/




